package org.aspire.core;

import org.aspire.core.sys.GSystem;
import org.aspire.data.Renderable;
import org.aspire.data.Updateable;
import org.aspire.graphics.Frame;
import org.aspire.graphics.Strip;
import org.aspire.math.geom.Dimension;

/******************************************************************************
 * Aspire2D uses a Game-Console-Engine architecture at its core. The Game
 * component provides the definition, both the resources and logic, behind a
 * generic 2D game. This is where game-specific instructions are defined.
 * <p>
 * Developers should extend this class to start programming their first 2D game
 * in Aspire2D. There are four main abstract methods that must be overridden
 * namely:
 * <p>
 * <ol>
 * 	<li>Initialize</li>
 * 	<li>Update</li>
 * 	<li>Render</li>
 * 	<li>Destroy</li>
 * </ol> 
 * <p>
 * Both Initialize and Destroy are called outside the main game loop. These
 * methods should contain what the game must do at the before and after the
 * processing of the loop respectively.
 * <p>
 * The Update and Render methods are continuously called during the main
 * loop. This method should contain the game logic processing: what to do with
 * user input and real-time data feed and what to display to the user.
 * 
 * @author JPACarabuena
 *****************************************************************************/
public abstract class Game implements Updateable, Renderable, Config {

	// ========================================================================
	// Constants
	// ========================================================================

	// ========================================================================
	// Static Methods
	// ========================================================================
	
	// ========================================================================
	// Fields
	// ========================================================================
	
	/**************************************************************************
	 * The working title for this game.
	 * 
	 * Default: Aspire Engine
	 *************************************************************************/
	private String gameTitle = "Aspire Engine";
	
	/**************************************************************************
	 * The working icon for this game.
	 *************************************************************************/
	private Frame gameIcon;
	
	/**************************************************************************
	 * The size of the screen display.
	 * 
	 * Default: 240x320
	 *************************************************************************/
	private Dimension displaySize = new Dimension(240, 320); 
	
	/**************************************************************************
	 * Contains the base path where the game resource is stored.
	 *************************************************************************/
	private String resourcePath;
	
	/**************************************************************************
	 * The FPS rate of this game.
	 * 
	 * Default: 60
	 *************************************************************************/
	private int fps = 60;
	
	/**************************************************************************
	 * Whether or not loop controller will regulate process.
	 * 
	 * Default: true
	 *************************************************************************/
	private boolean regulate = true;
	
	/**************************************************************************
	 * Whether or not update is constant.
	 * 
	 * Default: true
	 *************************************************************************/
	private boolean smooth = true;
	
	/**************************************************************************
	 * The units of time that the timer will use.
	 * 
	 * Default: 1000
	 *************************************************************************/
	private int resolution = 1000;
	
	/**************************************************************************
	 * The engine that will be processing this game.
	 *************************************************************************/
	private Engine engine;
	
	// ========================================================================
	// Constructors
	// ========================================================================
	
	// ========================================================================
	// Getters & Setters
	// ========================================================================
	
	/**************************************************************************
	 * Returns the width of the screen in integer precision.
	 * 
	 * @return	the width of the screen.
	 *************************************************************************/
	public int getWidth() {
		return GSystem.SCREEN_RESOLUTION.getWidthInt();
	}
	
	/**************************************************************************
	 * Returns the height of the screen in integer precision.
	 * 
	 * @return the height of the screen.
	 *************************************************************************/
	public int getHeight() {
		return GSystem.SCREEN_RESOLUTION.getHeightInt();
	}
	
	/**************************************************************************
	 * Synchronize the game with engine so that this game can invoke various
	 * functions provided by the engine such as file loading and saving, etc.
	 * 
	 * @param engine the engine that will be processing this game.
	 *************************************************************************/
	protected void setGameEngine(Engine engine) {
		this.engine = engine;
	}
	
	// ========================================================================
	// Override Methods
	// ========================================================================

	@Override
	public String getGameTitle() {
		return this.gameTitle;
	}
	
	@Override
	public Frame getGameIcon() {
		return this.gameIcon;
	}
	
	@Override
	public Dimension getScreenDisplaySize() {
		return this.displaySize;
	}
	
	@Override
	public String getBaseResourcePath() {
		return this.resourcePath;
	}
	
	@Override
	public int getFPS() {
		return this.fps;
	}
	
	@Override
	public boolean isProcessRegulated() {
		return this.regulate;
	}
	
	@Override
	public boolean isUpdateSmooth() {
		return this.smooth;
	}
	
	@Override
	public int getResolution() {
		return this.resolution;
	}
	
	@Override
	public void setGameTitle(String title) {
		this.gameTitle = title;
	}
	
	@Override
	public void setGameIcon(Frame icon) {
		this.gameIcon = icon;
	}
	
	@Override
	public void setScreenDisplaySize(float width, float height) {
		this.displaySize = new Dimension(width, height);
	}
	
	@Override
	public void setScreenDisplaySize(Dimension size) {
		this.displaySize = size;
	}
	
	@Override
	public void setBaseResourcePath(String str) {
		this.resourcePath = str;
	}
	
	@Override
	public void setFPS(int fps) {
		this.fps = fps;
		if(this.fps <= 0) {
			this.fps = 1;
		}
	}
	
	@Override
	public void enableRegulateProcess(boolean regulate) {
		this.regulate = regulate;
	}
	
	@Override
	public void enableSmoothUpdate(boolean smooth) {
		this.smooth = smooth;
	}
	
	@Override
	public void setResolution(int resolution) {
		this.resolution = resolution;
	}
	
	// ========================================================================
	// Methods
	// ========================================================================
	
	/**************************************************************************
	 * Returns the current FPS rate calculated by the game engine. The FPS
	 * represents the number of frames rendered by the engine at the current
	 * iteration.
	 * 
	 * @return	the current FPS rate.
	 *************************************************************************/
	public int getCurrentFPS() {
		return this.engine.getCurrentFPS();
	}
	
	public Frame getFrame(String path) {
		return this.engine.getFrame(path);
	}
	
	public Strip getStrip(String path, int col, int row) {
		return this.engine.getStrip(path, col, row);
	}
	
	/**************************************************************************
	 * Game resources initialization. This is where important components of the
	 * game should be loaded, created and initialized to avoid unwanted errors
	 * or exception during runtime.
	 *************************************************************************/
	public abstract void init();
	
	/**************************************************************************
	 * Game resources cleanup. This is where important components of the game
	 * using up system memory should be destroyed or released.
	 *************************************************************************/
	public abstract void destroy();

	// ========================================================================
	// Inner & Anonymous Classes
	// ========================================================================
}